-
Notifications
You must be signed in to change notification settings - Fork 4
Add Blockchain RPC methods #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- getblockcount - getblockhash - getblockfilter - getblockheader - getrawmempool - getrawtransaction
d73bb7a to
6543635
Compare
- add integration tests for blockchain methods
6543635 to
3a16fa4
Compare
ValuedMammal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far I agree with the way you've defined the client methods. I mainly focused on reviewing the implementation of the client code, and haven't spent as much time looking at the test code yet.
By convention, the commits should appear as type(module): Summary, for example
3a16fa4 test: Add integration tests
6f95a7f feat(client): Add blockchain methods
Other notes:
- Going forward try to have more descriptive API docs
- We should look into testing the client using
corepc_nodeto minimize the amount of manual testing needed and so we can run the integration tests in CI.
| let bytes: Vec<u8> = Vec::<u8>::from_hex(&hex_string).map_err(Error::HexToBytes)?; | ||
|
|
||
| let block: Block = deserialize(&bytes) | ||
| .map_err(|e| Error::InvalidResponse(format!("failed to deserialize block: {e}")))?; | ||
|
|
||
| Ok(block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For things that can be consensus decoded directly from a hex string, like Block, Header, and Transaction, I think it will be easier to use deserialize_hex and have a new Error::DecodeHex error that wraps the FromHexError.
| let bytes: Vec<u8> = Vec::<u8>::from_hex(&hex_string).map_err(Error::HexToBytes)?; | |
| let block: Block = deserialize(&bytes) | |
| .map_err(|e| Error::InvalidResponse(format!("failed to deserialize block: {e}")))?; | |
| Ok(block) | |
| bitcoin::consensus::encode::deserialize_hex(&hex_string).map_err(Error::DecodeHex) | |
| pub fn get_block_verbose(&self, block_hash: &BlockHash) -> Result<GetBlockVerboseOne, Error> { | ||
| let res: GetBlockVerboseOne = self.call("getblock", &[json!(block_hash), json!(1)])?; | ||
| Ok(res) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume we first want to deserialize the response as a type from corepc_types (e.g. v29::GetBlockVerboseOne), and then call into_model on it. Also we'll need a test for it.
| let raw: serde_json::Value = self.call("getblockhash", &[json!(height)])?; | ||
|
|
||
| let hash_str = match raw { | ||
| serde_json::Value::String(s) => s, | ||
| serde_json::Value::Object(obj) => obj | ||
| .get("hash") | ||
| .and_then(|v| v.as_str()) | ||
| .ok_or_else(|| Error::InvalidResponse("getblockhash: missing 'hash' field".into()))? | ||
| .to_string(), | ||
| _ => { | ||
| return Err(Error::InvalidResponse( | ||
| "getblockhash: unexpected response type".into(), | ||
| )); | ||
| } | ||
| }; | ||
|
|
||
| BlockHash::from_str(&hash_str).map_err(Error::HexToArray) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems complicated. Don't we always expect the value to be String?
| let raw: serde_json::Value = self.call("getblockhash", &[json!(height)])?; | |
| let hash_str = match raw { | |
| serde_json::Value::String(s) => s, | |
| serde_json::Value::Object(obj) => obj | |
| .get("hash") | |
| .and_then(|v| v.as_str()) | |
| .ok_or_else(|| Error::InvalidResponse("getblockhash: missing 'hash' field".into()))? | |
| .to_string(), | |
| _ => { | |
| return Err(Error::InvalidResponse( | |
| "getblockhash: unexpected response type".into(), | |
| )); | |
| } | |
| }; | |
| BlockHash::from_str(&hash_str).map_err(Error::HexToArray) | |
| let hex: String = self.call("getblockhash", &[json!(height)])?; | |
| Ok(hex.parse()?) |
| } | ||
|
|
||
| /// Get block filter | ||
| pub fn get_block_filter(&self, block_hash: BlockHash) -> Result<GetBlockFilter, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency we should decide whether the API can take a block hash by value or by reference.
| pub fn get_block_filter(&self, block_hash: BlockHash) -> Result<GetBlockFilter, Error> { | |
| pub fn get_block_filter(&self, block_hash: &BlockHash) -> Result<GetBlockFilter, Error> { |
Description
This PR adds the following methods:
Fixes #4
Depends on #3
Checklists
All Submissions:
cargo fmtandcargo clippybefore committingNew Features:
CHANGELOG.md